<template>
    <el-form label-width="100px">
        <el-form-item label="SPU的名称">
            <el-input placeholder="请你输入SPU名称" v-model="SpuParams.spuName"></el-input>
        </el-form-item>
        <el-form-item label="SPU的品牌">
            <el-select v-model="SpuParams.tmId">
                <el-option v-for="item in allTrademark" :key="item.id" :label="item.tmName" :value="item.id"></el-option>
            </el-select>
        </el-form-item>
        <el-form-item label="SPU描述">
            <el-input type="textarea" placeholder="请你输入SPU描述" v-model="SpuParams.description"></el-input>
        </el-form-item>
        <el-form-item label="SPU图片">
            <!-- 
                v-model:file-list 展示默认图片
                action 上传图片的接口地址
                list-type 文件列表的类型
                on-preview 文件预览的钩子
                on-remove 文件删除的钩子
             -->
            <el-upload
                v-model:file-list="imgList"
                action="/api/admin/product/fileUpload"
                list-type="picture-card"
                :on-preview="handlePictureCardPreview"
                :on-remove="handleRemove"
                :before-upload="handlerUpload"
            >
                <el-icon><Plus /></el-icon>
            </el-upload>
            <el-dialog v-model="dialogVisible">
                <img w-full :src="dialogImageUrl" alt="Preview Image" style="width: 100%;height: 100%;"/>
            </el-dialog>
        </el-form-item>
        <el-form-item label="SPU销售属性">
            <!-- 展示销售属性的下拉菜单 -->
            <el-select :placeholder="unSelectSaleAttr.length?`还未选择${unSelectSaleAttr.length}个`:'无'" v-model="saleAttrIdAndValueName">
                <el-option v-for="item in unSelectSaleAttr" :key="item.id" :label="item.name" :value="`${item.id}:${item.name}`"></el-option>
            </el-select>
            <el-button type="primary" size="default" icon="Plus" style="margin-left: 10px;" :disabled="saleAttrIdAndValueName?false:true" @click="addSaleAttr">添加属性</el-button>
            <!-- table展示销售属性与属性值的地方 -->
            <el-table border style="margin: 10px 0px;" :data="saleAttr">
                <el-table-column label="序号" type="index" align="center" width="80px"></el-table-column>
                <el-table-column label="销售属性名字" width="120px" prop="saleAttrName"></el-table-column>
                <el-table-column label="销售属性值">
                    <!-- row是当前销售属性对象 -->
                    <template #="{row,$index}">
                        <el-tag
                            v-for="item in row.spuSaleAttrValueList"
                            :key="item.id"
                            closable
                            class="mx-1"
                            style="margin: 0px 5px;"
                            @close="row.spuSaleAttrValueList.splice($index,1)"
                        >
                            {{ item.saleAttrValueName }}
                        </el-tag>
                        <el-input placeholder="请你输入属性值" size="small" style="width: 100px;" v-if="row.flag==true" v-model="row.saleAttrValue" @blur="toLook(row)"></el-input>
                        <el-button type="primary" size="samll" icon="Plus" v-else @click="toEdit(row)"></el-button>
                    </template>
                </el-table-column>
                <el-table-column label="操作" width="120px">
                    <template #="{row,$index}">
                        <el-button type="primary" size="small" icon="Delete" @click="saleAttr.splice($index,1)"></el-button>
                    </template>
                </el-table-column>
            </el-table>
        </el-form-item>
        <el-form-item>
            <el-button type="primary" size="default" @click="save" :disabled="saleAttr.length>0?false:true">保存</el-button>
            <el-button type="primary" size="default" @click="cancel">取消</el-button>
        </el-form-item>
    </el-form>
</template>

<script lang="ts" setup name="SpuForm">
    // 引入ts类型
    import type {SaleAttrValue,HasSaleAttr,SaleAttr,SpuImage,Trademark,SpuData,AllTrademark,SpuHasImag,SaleAttrResponseData,HasSaleAttrResponseData} from '@/api/product/spu/type'
    import {reqAddOrUpdateSpu,reqAllTradeMark,reqSpuImageList,reqSpuHasSaleAttr,reqAllSaleAttr} from '@/api/product/spu'
    import {ref} from 'vue'
    import { ElMessage } from 'element-plus'
    import {computed} from 'vue'

    // 声明事件
    let $emit=defineEmits(['changeScene'])
    // 存储已有的品牌数据
    let allTrademark=ref<Trademark[]>([])
    // 商品图片
    let imgList=ref<SpuImage[]>([])
    // 已有的Spu销售属性
    let saleAttr=ref<SaleAttr[]>([])
    // 全部的销售属性
    let allSaleAttr=ref<HasSaleAttr[]>([])
    // 存储已有的Spu对象
    let SpuParams=ref<SpuData>({
        category3Id:'', //三级分类的Id
        spuName:'', // Spu的名字
        description:'', // Spu的描述
        tmId:'', // 品牌的Id
        spuImageList:[],// 照片墙
        spuSaleAttrList:[] 
    })
    // 控制对话框的显示与隐藏效果
    let dialogVisible=ref<boolean>(false)
    // 存储预览图片的地址
    let dialogImageUrl=ref<string>('')
    // 计算当前Spu还未拥有的销售属性
    let unSelectSaleAttr=computed(()=>{
        // 全部销售属性：颜色、版本、尺码
        let unSelectAttr=allSaleAttr.value.filter(item=>{
            return saleAttr.value.every(item1=>{
                return item.name!=item1.saleAttrName
            })
        })
        return unSelectAttr
    })
    // 收集将来还未选择的销售属性的ID与名字
    let saleAttrIdAndValueName=ref<string>('')


    // 取消按钮回调，通知父组件切换为场景0，展示SPU数据
    function cancel(){
        $emit('changeScene',{flag:0,params:'update'}) // params控制返回当前页还是第一页
    }

    // 给子组件书写一个方法,spu即为父组件传递过来的spu对象【不完整】
    const initHasSpuData=async (spu:SpuData)=>{
        // 存储已有的Spu对象，将来在模版中展示
        SpuParams.value=spu
        // 获取全部品牌的数据
        let result:AllTrademark=await reqAllTradeMark()
        // 获取某一个品牌下全部售卖的商品的图片
        let result1:SpuHasImag=await reqSpuImageList(spu.id as number)
        // 获取已有的Spu销售属性
        let result2:SaleAttrResponseData=await reqSpuHasSaleAttr(spu.id as number)
        // 获取整个项目全部Spu销售属性
        let result3:HasSaleAttrResponseData=await reqAllSaleAttr()
        // 存储全部品牌的数据
        allTrademark.value=result.data
        // Spu对应的商品图片
        imgList.value=result1.data.map((item)=>{
            return {
                name:item.imgName,
                url:item.imgUrl
            }
        })
        // 存储已有的Spu销售属性
        saleAttr.value=result2.data
        // 存储全部的销售属性
        allSaleAttr.value=result3.data
    }

    // 照片墙点击预览按钮触发的方法
    function handlePictureCardPreview(file:any){
        dialogImageUrl.value=file.url
        // 对话框显示
        dialogVisible.value=true
    }

    // 照片墙删除文件的钩子
    function handleRemove(){
        console.log(123)
    }

    // 文件上传前的钩子，约束文件的大小与类型
    function handlerUpload(file:any){
        if(file.type=='image/jpg'||file.type=='image/jpeg'||file.type=='image/png'||file.type=='image/gif'){
            if(file.size/1024/1024<3){
                
                return true
            }else{
                ElMessage({
                    type:'error',
                    message:'上传文件大小务必小于3M'
                })
            }
            
        }else{
            ElMessage({
                    type:'error',
                    message:'上传文件类型务必是png|jpg|gif|jpeg'
                })
        }
        return false
    }

    // 添加销售属性的方法
    function addSaleAttr(){
        // 解构
        const [baseSaleAttrId,saleAttrName]=saleAttrIdAndValueName.value.split(':')
        // 准备新的属性对象,将来带给服务器对象
        let newSaleAttr:SaleAttr={
            baseSaleAttrId,
            saleAttrName,
            spuSaleAttrValueList:[]
        }
        // 追加到数组中
        saleAttr.value.push(newSaleAttr)
        // 清空收集的数据
        saleAttrIdAndValueName.value=''
    }

    // 新增属性值按钮的回调
    function toEdit(row:SaleAttr){
        // 点击按钮的时候，input组件出现，切换为编辑模式
        row.flag=true
        row.saleAttrValue=''
    }
    
    // 表单元素失去焦点回调
    function toLook(row:SaleAttr){
        // 整理收集的属性ID与属性的值的名字
        const {baseSaleAttrId,saleAttrValue}=row
        // 整理成服务器需要的属性值形式
        let newSaleAttrValue:SaleAttrValue={
            baseSaleAttrId,
            saleAttrValueName:(saleAttrValue as string)
        }
        // 非法情况判断
        if(saleAttrValue?.trim()==''){
            ElMessage({
                type:'error',
                message:'属性值不能为空'
            })
            return
        }
        // 判断属性值是否在数组中存在
        let repeat=row.spuSaleAttrValueList.find(item=>{
            return item.saleAttrValueName==saleAttrValue
        })
        if(repeat){
            ElMessage({
                type:'error',
                message:'属性值重复'
            })
            return
        }
        // 追加新增的属性值对象
        row.spuSaleAttrValueList.push(newSaleAttrValue)
        // 切换为查看模式
        row.flag=false
    }
    
    // 保存按钮的回调
    async function save(){
        // 整理照片墙数据
        SpuParams.value.spuImageList=imgList.value.map((item:any)=>{
            return {
               imgName:item.name,
               imgUrl:(item.response&&item.response.data)||item.url
            }
        })
        // 整理销售属性的数据
        SpuParams.value.spuSaleAttrList=saleAttr.value
        // 发请求
        let result=await reqAddOrUpdateSpu(SpuParams.value)
        if(result.code==200){
            ElMessage({
                type:'success',
                message:SpuParams.value.id?'更新成功':'添加成功'
            })
            // 通知父组件切换场景
            $emit('changeScene',{flag:0,params:SpuParams.value.id?'update':'add'})
        }else{
            ElMessage({
                type:'error',
                message:SpuParams.value.id?'更新失败':'添加失败'
            })
        }
    }

    // 添加Spu初始化的方法
    async function initAddSpu(c3Id:number){
        // 清空数据
        Object.assign(SpuParams.value,{
            category3Id:'', //三级分类的Id
            spuName:'', // Spu的名字
            description:'', // Spu的描述
            tmId:'', // 品牌的Id
            spuImageList:[],// 照片墙
            spuSaleAttrList:[] 
        })
        // 清空照片墙
        imgList.value=[]
        // 清空销售属性
        saleAttr.value=[]
        saleAttrIdAndValueName.value=''
        // 存储三级分类的Id
        SpuParams.value.category3Id=c3Id
        // 获取全部品牌的数据
        let result:AllTrademark=await reqAllTradeMark()
        // 获取整个项目全部Spu销售属性
        let result1:HasSaleAttrResponseData=await reqAllSaleAttr()
        // 存储数据
        allTrademark.value=result.data
        allSaleAttr.value=result1.data
    }

    // 对外暴露给父组件
    defineExpose({initHasSpuData,initAddSpu}) 
</script>

<style scoped>
     .el-input {
        --el-input-width: 220px;
    }

    .el-select {
        --el-select-width: 220px;
    }
</style>